Skip to content

04 Docker 镜像安装 ROS 2 Humble

适用平台:NVIDIA Jetson Xavier NX / AGX Xavier / Orin 系列(JetPack 5.x,L4T R35.x)

前置条件:已通过 SDK Manager 刷好 JetPack 5.x 系统(Ubuntu 20.04),板卡可正常联网

本文方案的优势:容器内运行原生 Ubuntu 22.04,可直接使用 apt install ros-humble-* 安装任意 ROS 2 官方包,无需从源码编译。GPU 通过 --runtime nvidia 挂载宿主机 CUDA 库,无需在容器内额外安装 CUDA 栈。


与 dustynv 预构建镜像方案的对比

dustynv 预构建镜像本文自建 22.04 镜像
容器底层系统Ubuntu 20.04(focal)Ubuntu 22.04(jammy)
ROS 2 安装方式源码编译apt 官方预编译包
apt install ros-humble-*❌ 不可用✅ 可用
CUDA 支持容器内自带完整 CUDA 栈通过 --runtime nvidia 挂载宿主机 CUDA
镜像体积较大(7GB+)较小(约 3-4GB)
构建方式直接 docker pull需本地 docker build

如果你的项目需要频繁 apt 安装 ROS 包(Nav2、robot_localization、turtlebot3 等),推荐本方案。


一、安装 Docker

JetPack 5.x 默认不一定预装 Docker,需要手动安装:

bash
sudo apt update
sudo apt install -y docker.io

安装完成后启动 Docker 并设置开机自启:

bash
sudo systemctl enable --now docker

将当前用户加入 docker 组,避免每次都要 sudo

bash
sudo usermod -aG docker $USER

执行完后需要重新登录(或重启)才能生效。 重新登录后验证:

bash
docker info | grep -i runtime

二、安装并配置 NVIDIA Container Runtime

2.1 安装 nvidia-container-runtime

bash
sudo apt install -y nvidia-container-runtime

2.2 配置 Docker

创建或编辑 /etc/docker/daemon.json,同时配置 NVIDIA Runtime 和国内镜像加速:

bash
sudo tee /etc/docker/daemon.json <<'EOF'
{
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "registry-mirrors": [
        "https://docker.1ms.run",
        "https://docker.xuanyuan.me"
    ]
}
EOF

重启 Docker:

bash
sudo systemctl restart docker

验证:

bash
docker info | grep -i runtime

预期输出应同时包含 nvidiarunc

 Runtimes: io.containerd.runc.v2 nvidia runc
 Default Runtime: runc

注意:国内镜像加速器的可用性经常变化。如果上述地址失效,可搜索"Docker 国内镜像加速"获取最新可用地址,替换 registry-mirrors 数组中的 URL 即可。


三、构建 ROS 2 Humble 镜像

3.1 创建工作目录

bash
mkdir -p ~/ros2-docker && cd ~/ros2-docker

3.2 编写 Dockerfile

bash
cat > Dockerfile <<'EOF'
FROM arm64v8/ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive
ENV LANG=C.UTF-8

# 基础工具
RUN apt-get update && apt-get install -y \
    curl gnupg2 lsb-release software-properties-common \
    python3-pip wget git

# 添加 ROS 2 apt 源
RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
    -o /usr/share/keyrings/ros-archive-keyring.gpg && \
    echo "deb [arch=arm64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu jammy main" \
    > /etc/apt/sources.list.d/ros2.list

# 安装 ROS 2 Humble Desktop
RUN apt-get update && apt-get install -y \
    ros-humble-desktop \
    python3-colcon-common-extensions \
    python3-rosdep \
    && rm -rf /var/lib/apt/lists/*

# 初始化 rosdep(仅 init,update 在容器内手动执行以避免构建时网络超时)
RUN rosdep init || true

# 自动 source ROS 2 环境
RUN echo "source /opt/ros/humble/setup.bash" >> /etc/bash.bashrc

ENTRYPOINT ["/bin/bash"]
EOF

Dockerfile 说明:

指令作用
FROM arm64v8/ubuntu:22.04基础镜像,arm64 架构的 Ubuntu 22.04。Jetson 是 aarch64 平台,必须使用 arm64 版本
添加 ROS 2 apt 源从 ROS 官方获取 GPG 密钥并添加 jammy(22.04)的 apt 仓库
ros-humble-desktopROS 2 Humble 完整桌面版,含 rviz2、rqt 等 GUI 工具。如需精简可替换为 ros-humble-ros-base
python3-colcon-common-extensionscolcon 构建工具,编译自定义 ROS 2 工作空间时需要
python3-rosdepROS 依赖管理工具
rosdep init || true初始化 rosdep 源列表。加 || true 是因为构建时可能因网络问题失败,不影响后续使用

3.3 构建镜像

bash
cd ~/ros2-docker
docker build -t ros2:humble-22.04 .

构建过程需要下载约 2-3GB 的包,耗时取决于网络速度,通常 10-30 分钟。

如果构建中途因网络问题失败:直接重新执行 docker build 即可,Docker 会从失败的那一层继续,已完成的步骤不会重复执行。


四、启动容器

4.1 首次创建并运行

bash
docker run --runtime nvidia -it \
    --name ros2_humble \
    --network=host \
    --privileged \
    -v /dev:/dev \
    -v ~/ros2_ws:/ros2_ws \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e DISPLAY=$DISPLAY \
    -e ROS_DOMAIN_ID=0 \
    ros2:humble-22.04

4.2 启动参数详解

参数作用
--runtime nvidia使用 NVIDIA 容器运行时,让容器能访问 GPU 和 CUDA。不加则容器内无法使用 GPU
-it-i(保持标准输入打开)+ -t(分配伪终端),两者合用才能在容器内正常交互
--name ros2_humble给容器命名,便于后续通过名称管理。不加则 Docker 会随机生成名称
--network=host容器直接使用宿主机网络栈,不做网络隔离。ROS 2 的 DDS 通信依赖组播发现机制,必须使用 host 网络,否则多节点之间无法互相发现
--privileged赋予容器几乎所有内核权限,允许访问宿主机设备。安全性有牺牲,但访问硬件设备时必须开启
-v /dev:/dev将宿主机 /dev 挂载到容器内,使容器能访问串口(/dev/ttyUSB0/dev/ttyACM0)、USB 摄像头(/dev/video*)、LiDAR 等硬件设备。需配合 --privileged 使用
-v ~/ros2_ws:/ros2_ws将宿主机的工作空间目录挂载到容器内,双向同步——容器内编译的产物宿主机也能看到,宿主机上修改的代码容器内立刻生效。容器删除后数据不会丢失
-v /tmp/.X11-unix:/tmp/.X11-unix挂载 X11 的 Unix socket,让容器内的 GUI 程序(rviz2、rqt 等)能通过宿主机的 X Server 显示窗口
-e DISPLAY=$DISPLAY传递显示环境变量,告诉 GUI 程序往哪个显示器输出。如果 GUI 打不开,先在宿主机执行 xhost +local:docker
-e ROS_DOMAIN_ID=0设置 ROS 2 的 Domain ID,相同 ID 的节点才能互相发现。默认为 0,多套 ROS 2 系统共存时用不同数字隔离

4.3 验证环境

进入容器后,ROS 2 环境已自动 source,直接验证:

bash
ros2 topic list

预期输出:

/parameter_events
/rosout

五、安装 ROS 2 功能包

这是本方案的核心优势——可以直接用 apt 安装任意 ROS 2 官方包。

5.1 常用包安装示例

bash
apt update

# Navigation2(自主导航)
apt install -y ros-humble-navigation2 ros-humble-nav2-bringup

# robot_localization(多传感器融合定位)
apt install -y ros-humble-robot-localization

# TurtleBot3
apt install -y ros-humble-turtlebot3 ros-humble-turtlebot3-msgs

# SLAM Toolbox
apt install -y ros-humble-slam-toolbox

# tf2 相关
apt install -y ros-humble-tf2-ros ros-humble-tf2-tools

# USB 摄像头
apt install -y ros-humble-usb-cam

# 串口通信
apt install -y ros-humble-serial-driver

5.2 搜索可用包

bash
apt search ros-humble- | grep <关键>

5.3 初始化 rosdep(首次使用时执行一次)

如果你需要用 rosdep 自动解析依赖,首次需要手动完成 update:

bash
rosdep update

如果因网络问题超时,重试几次即可,或使用代理。


六、日常使用

6.1 退出容器

在容器内输入 exit 或按 Ctrl+D 即可退出。由于创建时使用了 --name 且没有加 --rm,容器退出后不会被删除。

6.2 重新进入已有容器

bash
docker start -ai ros2_humble

无需重新 docker run,之前在容器内安装的包和修改都还在。

6.3 在另一个终端进入同一容器

如果容器正在运行,想开第二个终端窗口:

bash
docker exec -it ros2_humble bash

6.4 查看容器状态

bash
# 查看正在运行的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

6.5 删除容器(谨慎操作)

bash
docker rm ros2_humble

删除后容器内安装的包会丢失,但通过 -v 挂载的目录(如 ~/ros2_ws)中的文件不受影响。

6.6 导出当前容器为新镜像

如果你在容器内装了很多包,想把当前状态保存下来(避免下次重新安装):

bash
docker commit ros2_humble ros2:humble-22.04-custom

之后可以基于新镜像创建容器,已安装的包都会保留。


七、常见问题

Q1: GUI 程序报错 cannot open display

宿主机(不是容器内)执行:

bash
xhost +local:docker

如果需要开机自动生效,可将此命令加入 ~/.bashrc

Q2: 容器内看不到串口设备

确认启动时加了 --privileged-v /dev:/dev。如果设备是在容器启动后才插入的,需要退出容器重新启动。

Q3: ROS 2 节点之间无法通信

检查是否使用了 --network=host。另外确认所有节点的 ROS_DOMAIN_ID 一致。

Q4: 构建镜像时下载超时

ROS 2 的 apt 源服务器在国外,下载可能较慢。可以在 Dockerfile 中将 Ubuntu 源替换为国内镜像。在 RUN apt-get update 之前添加:

dockerfile
RUN sed -i 's|http://ports.ubuntu.com|http://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list

ROS 2 源也可以使用清华镜像,将 Dockerfile 中添加 apt 源的那行替换为:

dockerfile
RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
    -o /usr/share/keyrings/ros-archive-keyring.gpg && \
    echo "deb [arch=arm64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu jammy main" \
    > /etc/apt/sources.list.d/ros2.list

Q5: 容器内 CUDA 是否可用

本方案通过 --runtime nvidia 自动挂载宿主机的 CUDA 库到容器内,无需在容器中单独安装 CUDA。验证方式:

bash
# 检查 CUDA 设备
ls /dev/nvhost-*

# 如果安装了 PyTorch 等框架,可以进一步验证
python3 -c "import torch; print(torch.cuda.is_available())"

Q6: 磁盘空间不足

构建后的镜像约 3-4GB,加上后续安装的 ROS 包,建议系统盘至少有 20GB 可用空间。如果根分区在 eMMC(通常只有 16GB),建议先将系统迁移到外部 NVMe/SD 卡后再操作。


参考资料

最近更新